﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SimpleRest.Core.Extensions.OAuth.Exceptions;
using SimpleRest.Core.Routing;

namespace SimpleRest.Core.Extensions.OAuth
{
    public static class OAuthExtensions
    {
        public static void AppendOAuthErrorHandling(this Configuration config)
        {
            if (config == null)
                config.ErrorHandler = ErrorHandler;
            else
                config.ErrorHandler += ErrorHandler;
        }

        private static void ErrorHandler(ErrorHandlerEventArgs e)
        {
            if (e.Exception.GetType().GetInterface(typeof(IOAuthException).FullName) != null)
            {
                IOAuthException oAuthException = e.Exception as IOAuthException;

                if (oAuthException != null)
                {
                    if (!string.IsNullOrEmpty(oAuthException.OAuthMessage))
                        e.ResponseMessage.Content = new OAuthErrorResponse() { error = oAuthException.OAuthMessage };
                }
            }
        }

        /// <summary>
        /// Adds oAuth message handler that invokes authorization service IsAuthorized if criteria is met.
        /// Adds error handler that shapes response as oAuth RFC states.  http://tools.ietf.org/html/rfc6749#section-5.2
        /// </summary>
        /// <param name="config"></param>
        public static void ApplyOAuthWorkflow(this Configuration config, bool applyOAuthResponseOverride = true)
        {
            ApplyOAuthWorkflow(config, null, applyOAuthResponseOverride);
        }

        /// <summary>
        /// Adds oAuth message handler that invokes authorization service IsAuthorized if criteria is met.
        /// Adds error handler that shapes response as oAuth RFC states.  http://tools.ietf.org/html/rfc6749#section-5.2
        /// </summary>
        /// <param name="config"></param>
        public static void ApplyOAuthWorkflow(this Configuration config, IAuthorizationAuthority authorizationService, bool applyOAuthResponseOverride = true)
        {
            if (config.MessageHandlers == null)
                config.MessageHandlers = new List<IHttpMessageHandler>();

            if (!config.MessageHandlers.Any(d => d is OAuthMessageHandler))
                config.MessageHandlers.Add(new OAuthMessageHandler(authorizationService));

            if (applyOAuthResponseOverride)
                config.AppendOAuthErrorHandling();
        }

        /// <summary>
        /// Adds oAuth message handler that invokes authorization service IsAuthorized if criteria is met.
        /// Adds error handler that shapes response as oAuth RFC states.  http://tools.ietf.org/html/rfc6749#section-5.2
        /// </summary>
        /// <param name="config"></param>
        public static void ApplyOAuthWorkflow<T>(this Configuration config, bool applyOAuthResponseOverride = true) where T : IAuthorizationAuthority, new()
        {
            if (config.MessageHandlers == null)
                config.MessageHandlers = new List<IHttpMessageHandler>();

            if (!config.MessageHandlers.Any(d => d is OAuthMessageHandler))
                config.MessageHandlers.Add(new OAuthMessageHandler<T>());

            if (applyOAuthResponseOverride)
                config.AppendOAuthErrorHandling();
        }
    }

    /// <summary>
    /// http://tools.ietf.org/html/rfc6749#section-5.2
    /// </summary>
    public class OAuthErrorResponse
    {
        public string error { get; set; }
    }
}
